#ifndef __MAIN_CPP__
#define __MAIN_CPP__

#include "lzjlex.cpp"

#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>

using namespace std;

void test();

/**
 * 看README看README看README看README看README看README
 * 看README看README看README看README看README看README
 * 看README看README看README看README看README看README
 */
int main(int argc, char *args[]) {
    string header = "* Lin Zejia (R) MIDL Lexical Analyzer Version 1.0.0 for x64\n"
                    "* Copyright(C) Lin Zejia. All rights reserved.\n";
    string asteroids = "\n*************************************************************\n";
    cout << asteroids << header << "* Welcome to LzjLex!\n* Happy lexical analyzing!" << asteroids
         << "\n\n";

    string prompt =
        "Invalid arguments! Please see README for detail.\n"
        "Usage: main.exe [std | auto | {input filepath} {output filepath}]\n"
        "       If you choose [std], the program would read and write from console.\n"
        "       If you choose [auto], the program would read from \'./testfiles\' and write to "
        "\'./results\'\n";
    if (argc == 1 || argc > 3) {
        cout << prompt;
        system("pause");
        return 0;
    } else if (argc == 2) {
        if (strcmp(args[1], "std") == 0) {
            lzjlex(cin, cout);
        } else if (strcmp(args[1], "auto") == 0) {
            test();
        } else {
            cout << prompt;
            system("pause");
            return 0;
        }
    } else if (argc == 3) {
        fstream fin, fout;
        fin.open(args[1], std::fstream::in);
        fout.open(args[2], std::fstream::in | std::fstream::out | std::fstream::trunc);
        if (!fin.is_open()) {
            cout << "Fail to open " << args[1] << endl;
            system("pause");
            return 0;
        }
        if (!fout.is_open()) {
            cout << "Fail to open " << args[2] << endl;
            system("pause");
            return 0;
        }
        lzjlex(fin, fout);
    }

    return 0;
}

void test() {
    cout << "Running automatic test..\n";
    string baseInpath = "./testfiles/";
    string baseOutpath = "./results/";
    fstream fin, fout;
    vector<string> subpaths = {"keyword/",    "formula/", "identifier/",
                               "expression/", "complex/", "custom/"};
    vector<vector<string>> filenames = {
        {"test_1_kw.txt", "test_2_kw.txt"},
        {"test_3_formula.txt"},
        {"test_4_identifier.txt", "test_5_identifier_with_error.txt",
         "test_6_identifier_with_error.txt"},
        {"test_7_expression.txt"},
        {"test_8_complex.txt", "test_9_complex_with_escape.txt"},
        {"evil_line_1.txt", "error_prompt_2.txt", "keyword_3.txt", "escapes_4.txt"}};
    for (int i = 0; i < subpaths.size(); ++i) {
        for (int j = 0; j < filenames[i].size(); ++j) {
            string inPath = baseInpath + subpaths[i] + filenames[i][j];
            string outPath = baseOutpath + "result_" + filenames[i][j];
            fin.open(inPath, std::fstream::in);
            fout.open(outPath, std::fstream::in | std::fstream::out | fstream::trunc);
            if (!fin.is_open()) {
                cout << "Fail to open " << inPath << endl;
                continue;
            }
            if (!fout.is_open()) {
                cout << "Fail to open " << outPath << endl;
                continue;
            }
            cout << "Analyzing " << baseInpath + subpaths[i] + filenames[i][j] << endl;
            lzjlex(fin, fout);
            fin.close();
            fout.close();
        }
    }
}

#endif